﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SIGEB.Prototipo.Control;
using System.Collections;
using SIGEB.Modelo.moduloDocumentos;
using SIGEB.Modelo.moduloTipoDocumentos;
using SIGEB.Modelo.moduloEditorial;
using SIGEB.Modelo;
using SIGEB.Modelo.moduloPerfiles;

namespace SIGEB.Prototipo.Vista.moduloDocumentos
{

    public partial class frm_Documentos : frm_IMEC
    {

        #region "Constructores

        public frm_Documentos()
        {
            InitializeComponent();
            this.dgv_busqueda = dgv_listado;
            inicializarComponentes();
            
        }

        public frm_Documentos(controlPrincipal cp) : base(cp)
        {
            InitializeComponent();
            asignarUI(this.Controls);
            this.dgv_busqueda = dgv_listado;
            inicializarComponentes();
        }

        #endregion

        #region "eventos"

        private void cmb_tipodoc_TextChanged(object sender, EventArgs e)
        {
            actualizarTipoDocumento();
        }

        private void btn_buscar_Click(object sender, EventArgs e)
        {
            cargarDatosActuales();
            llenarDocumentos(datosActuales);
        }

        public override void hacerVisible(object[] arg)
        {
            aConsulta();
            llenarTiposBusqueda();
            cargarDatosAutor();
            cargarDatosEditorial();
            cargarTiposDocumento();
            llenarTipoDocumentos();
            cargarDatosActuales();
            llenarDocumentos(datosActuales);
        }

        public override void actualizar(object referencia, bibliotecaObservador.EventoActualizacion e)
        {
            int numTipo = (int)referencia;
            if (numTipo == conjuntoBase.CONJAUTORES)
            {
                cargarDatosAutor();
            }
            else if (numTipo == conjuntoBase.CONJEDITORIALES)
            {
                cargarDatosEditorial();
            }
            else if (numTipo == conjuntoBase.CONJTIPODOCS)
            {
                cargarTiposDocumento();
            }
            else if (numTipo == conjuntoBase.CONJDOCUMENTOS)
            {
                cargarDatosActuales();
                llenarDocumentos(datosActuales);
            }
        }

        private void dgv_listado_SelectionChanged(object sender, EventArgs e)
        {
            if (estado.CONSULTANDO())
            {
                actual = getDocumentoSelected();
                escribirActual();
            }
            actualizarControles();
        }

        #endregion

        #region "metodos"

        private void escribirActual()
        {
            if (actual != null)
            {
                txt_Autor.Text = actual.autorD.nombre;
                txt_clasificacion.Text = actual.clasificacion;
                txt_descripcion.Text = actual.descriptores;
                txt_editorial.Text = actual.editorialD.nombre;
                txt_idDoc.Text = actual.codDocumento;
                txt_serie.Text = actual.serie;
                txt_Titulo.Text = actual.titulo;
                seleccionarTipoDocumento(actual.atributos.codTipoDocumento);
                escribirValores(actual.valores);
            }
        }

        private void escribirValores(LinkedList<valor> linkedList)
        {
            if (linkedList != null && campos != null)
            {
                foreach (valor act in linkedList)
                {
                    campoDocumento act2 = campoPorAtributo(act.idAtributo);
                    if (act2 != null)
                    {
                        act2.setValor(act.campoText);
                    }
                }
            }
        }

        private void seleccionarTipoDocumento(string codTipoDoc)
        {
            cmb_tipodoc.SelectedItem = null;
            foreach (object act in cmb_tipodoc.Items)
            {
                if (((comboBoxItem)act).id == codTipoDoc)
                {
                    cmb_tipodoc.SelectedItem = act;
                }
            }
        }

        private campoDocumento campoPorAtributo(string idAtributo)
        {
            if (campos != null)
            {
                foreach (campoDocumento act in campos)
                {
                    if (act.id == idAtributo)
                    {
                        return act;
                    }
                }
            }
            return null;
        }

        private void actualizarTipoDocumento()
        {
            tipoDocumento tipoDocActual = getTipoDocumentoSelected();
            generarCampos(tipoDocActual);
            escribirCamposTipoDocumento();
        }

        private void llenarTipoDocumentos()
        {
            cmb_tipodoc.Items.Clear();
            if (tiposDocuemntos != null)
            {
                foreach (tipoDocumento act in tiposDocuemntos)
                {
                    cmb_tipodoc.Items.Add(new comboBoxItem(act.codTipoDocumento, act.nombre));
                }
            }
        }

        private void llenarTiposBusqueda()
        {
            cmb_tipoBusqueda.Items.Add(new comboBoxItem(TODO.ToString(), "Todo"));
            cmb_tipoBusqueda.Items.Add(new comboBoxItem(XAUTOR.ToString(), "Autor"));
            cmb_tipoBusqueda.Items.Add(new comboBoxItem(XTITULO.ToString(), "Título"));
            cmb_tipoBusqueda.Items.Add(new comboBoxItem(XLIBRE.ToString(), "Libre"));
            cmb_tipoBusqueda.Items.Add(new comboBoxItem(XCODIGO.ToString(), "Código"));
        }

        private void llenarDocumentos(LinkedList<documento> datos)
        {
            llenarColumnas();
            if (datos != null)
            {
                foreach (documento act in datos)
                {
                    dgv_listado.Rows.Add(act.codDocumento, act.titulo, act.autorD.nombre, act.editorialD.nombre, act.atributos.nombre);
                }
            }
        }

        private void llenarColumnas()
        {
            dgv_listado.Columns.Clear();
            dgv_listado.Columns.Add("idDoc", "Código de documento");
            dgv_listado.Columns.Add("Titulo", "Título");
            dgv_listado.Columns.Add("Autor", "Autor");
            dgv_listado.Columns.Add("Editorial", "Editorial");
            dgv_listado.Columns.Add("Formato", "Formato");
        }

        private tipoDocumento getTipoDocumentoSelected()
        {
            return buscarTipoDocumento(getTipoDocSelecedId());                            
        }

        private documento getDocumentoSelected()
        {
            documento nuevo = null;
            try
            {
                dgv_listado.Rows[dgv_listado.SelectedCells[0].RowIndex].Selected = true;
                String codigo = dgv_listado.SelectedRows[0].Cells[0].Value.ToString();
                if (!string.IsNullOrEmpty(codigo))
                {
                    nuevo = buscarDocumento(datosActuales, codigo);
                }
            }
            catch
            {
                return null;
            }
            return nuevo;
        }

        private documento buscarDocumento(LinkedList<documento> datos, String codigo)
        {
            if (datos != null && !String.IsNullOrEmpty(codigo))
            {
                foreach (documento act in datos)
                {
                    if (act.codDocumento == codigo)
                    {
                        return act;
                    }
                }
            }
            return null;
        }

        private tipoDocumento buscarTipoDocumento(string p)
        {
            if (tiposDocuemntos != null && !string.IsNullOrEmpty(p))
            {
                foreach (tipoDocumento act in tiposDocuemntos)
                {
                    if (act.codTipoDocumento == p)
                    {
                        return act;
                    }
                }
            }
            return null;
        }

        private string getTipoDocSelecedId()
        {
            try
            {
                return ((comboBoxItem)cmb_tipodoc.SelectedItem).id;
            }
            catch
            {
                return null;
            }
        }

        private void inicializarComponentes()
        {
            campos = new LinkedList<campoDocumento>();
        }

        #endregion

        #region "captura"

        private LinkedList<valor> valoresTipoDocumentos()
        {
            LinkedList<valor> nueva = new LinkedList<valor>();
            if (campos != null)
            {
                foreach (campoDocumento act in campos)
                {
                    valor n = new valor(act.id, act.valorActual());
                    nueva.AddLast(n);
                }
            }
            return nueva;
        }

        private string tipoDocSelectedId()
        {
            string code="";
            try
            {
                code = ((comboBoxItem)cmb_tipodoc.SelectedItem).id;
                return code;
            }
            catch
            {
                return "";
            }
        }

        private tipoDocumento tipoDocSelected()
        {
            return buscarTipoDocumento(tipoDocSelectedId());
        }

        private documento getFromFields()
        {
            try{
                if (string.IsNullOrEmpty(txt_totalEjemplares.Text))
                {
                    txt_totalEjemplares.Text = "0";
                }
                if (string.IsNullOrEmpty(txt_prestados.Text))
                {
                    txt_prestados.Text = "0";
                }
                if (string.IsNullOrEmpty(txt_reservados.Text))
                {
                    txt_reservados.Text = "0";
                }
                return new documento(txt_idDoc.Text, txt_Titulo.Text, chb_Virtual.Checked, txt_descripcion.Text, txt_clasificacion.Text, txt_serie.Text,
                    int.Parse(txt_totalEjemplares.Text), int.Parse(txt_reservados.Text), int.Parse(txt_prestados.Text), new autor(txt_Autor.Text), new editorial(txt_editorial.Text),
                    tipoDocSelected(), valoresTipoDocumentos());
            }
            catch{
                return null;
            }
        }

        private int tipoBusqueda()
        {
            try
            {
                string num = ((comboBoxItem)cmb_tipoBusqueda.SelectedItem).id;
                return int.Parse(num);
            }
            catch
            {
                return 0;
            }
        }

        #endregion

        #region "carga Datos"

        private void cargarDatosAutor()
        {
            AutoCompleteStringCollection a = new AutoCompleteStringCollection();
            try
            {
                txt_Autor.AutoCompleteCustomSource = autoresToString(cp.ctrlAutores.obtenerAutores());
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }
        }

        private void cargarDatosEditorial()
        {
            AutoCompleteStringCollection a = new AutoCompleteStringCollection();
            try
            {
                txt_editorial.AutoCompleteCustomSource = editorialToString(cp.ctrlEditorial.obtenerEditoriales());
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }
        }

        private void cargarTiposDocumento()
        {
            try
            {
                tiposDocuemntos = cp.ctrlDocumentos.tiposDocumentos();
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }
        }

        private void cargarDatosActuales()
        {
            try
            {
                datosActuales = devolverBusqueda();
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }
        }

        private LinkedList<documento> devolverBusqueda()
        {
            int tipo = tipoBusqueda();
            try
            {
                if (tipo == TODO)
                {
                    return cp.ctrlDocumentos.todosDocumentos();
                }
                else if (tipo == XAUTOR)
                {
                    return cp.ctrlDocumentos.documentoAutor(txb_busqueda.Text);
                }
                else if (tipo == XCODIGO)
                {
                    LinkedList<documento> a = new LinkedList<documento>();
                    a.AddLast(cp.ctrlDocumentos.documentoCodigo(txb_busqueda.Text));
                    return a;
                }
                else if (tipo == XLIBRE)
                {
                    return cp.ctrlDocumentos.documentoLibre(txb_busqueda.Text);
                }
                else if (tipo == XTITULO)
                {
                    return cp.ctrlDocumentos.documentoTitulo(txb_busqueda.Text);
                }
                else
                {
                    return null;
                }
                
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
            }
            return null;
        }

        private AutoCompleteStringCollection editorialToString(LinkedList<editorial> editoriales)
        {
            AutoCompleteStringCollection a = new AutoCompleteStringCollection();
            if (editoriales != null)
            {
                foreach (editorial act in editoriales)
                {
                    a.Add(act.nombre);
                }
            }
            return a;
        }

        private AutoCompleteStringCollection autoresToString(LinkedList<autor> autores)
        {
            AutoCompleteStringCollection a = new AutoCompleteStringCollection();
            if (autores != null)
            {
                foreach (autor act in autores)
                {
                    a.Add(act.nombre);
                }
            }
            return a;
        }

        #endregion

        #region "metodos botones"

        private void btn_autor_Click(object sender, EventArgs e)
        {
            objetoReturn r = new objetoReturn();
            cp.abrirVentana(this, controlPrincipal.VENANTA_AUTORES, new Object[] { r });
        }

        private void btn_editorial_Click(object sender, EventArgs e)
        {
            cp.abrirVentana(this, controlPrincipal.VENANTA_EDITORIAL, null);
        }

        private void btn_ejemplares_Click(object sender, EventArgs e)
        {
            if ((estado.CONSULTANDO() && actual != null) || estado.EDITANDO())
            {
                cp.abrirVentana(this, controlPrincipal.VENTANA_EJEMPLARES, new object[] { actual.codDocumento });
            }
        }

        #endregion

        #region "campos generados"

        private void generarCampos(tipoDocumento tipoDoc)
        {
            campos.Clear();
            pnl_atributos.Controls.Clear();
            if (tipoDoc != null && tipoDoc.atributos != null)
            {
                int count = 0;
                foreach (atributo act in tipoDoc.atributos)
                {
                    campos.AddLast(new campoDocumento(act.codAtributo, act.nombre, "", act.tipo, x, y + distY * count));
                    count++;
                }
            }
        }

        private void escribirCamposTipoDocumento()
        {
            pnl_atributos.Controls.Clear();
            if (campos != null)
            {
                foreach (campoDocumento act in campos)
                {
                    pnl_atributos.Controls.Add(act.campo());
                    pnl_atributos.Controls.Add(act.etiqueta());
                }
            }
        }

        #endregion

        #region "controles"

        private void actualizarBotones()
        {
            if (estado.CONSULTANDO())
            {
                btn_cancelar.Enabled = false;
                btn_editar.Enabled = cp.usuarioActualPuede(acciones.DOCS_MODIFICAR);
                btn_eliminar.Enabled = cp.usuarioActualPuede(acciones.DOCS_ELIMINAR);
                btn_guardar.Enabled = false;
                btn_Nuevo.Enabled = cp.usuarioActualPuede(acciones.DOCS_AGREGAR);
                btn_ejemplares.Enabled = actual != null && cp.usuarioActualPuede(acciones.EJEM_CONSULTAR);
                btn_notifi.Enabled = false;
            }
            else if (estado.EDITANDO())
            {
                btn_cancelar.Enabled = true;
                btn_editar.Enabled = false;
                btn_eliminar.Enabled = cp.usuarioActualPuede(acciones.DOCS_ELIMINAR);
                btn_guardar.Enabled = true;
                btn_Nuevo.Enabled = false;
                btn_ejemplares.Enabled = cp.usuarioActualPuede(acciones.EJEM_CONSULTAR);
                btn_notifi.Enabled = true;
            }
            else if (estado.AGREGANDO())
            {
                btn_cancelar.Enabled = true;
                btn_editar.Enabled = false;
                btn_eliminar.Enabled = false;
                btn_guardar.Enabled = true;
                btn_Nuevo.Enabled = false;
                btn_ejemplares.Enabled = false;
                btn_notifi.Enabled = true;
            }
        }

        private void deshabilitarCamposTipoDoc()
        {
            if (campos != null)
            {
                foreach (campoDocumento act in campos)
                {
                    act.campo().Enabled = false;
                }
            }
        }

        private void actualizarCampos()
        {
            if (estado.AGREGANDO())
            {
                txt_Autor.Enabled = true;
                cmb_tipodoc.Enabled = true;
                txt_clasificacion.Enabled = true;
                txt_descripcion.Enabled = true;
                txt_editorial.Enabled = true;
                txt_idDoc.Enabled = true;
                txt_serie.Enabled = true;
                txt_Titulo.Enabled = true;
                txt_totalEjemplares.Enabled = false;
                txt_reservados.Enabled = false;
                txt_prestados.Enabled = false;
                chb_Virtual.Enabled = true;
                habilitarCamposTipoDoc();
            }
            else if (estado.CONSULTANDO())
            {
                txt_Autor.Enabled = false;
                cmb_tipodoc.Enabled = false;
                txt_clasificacion.Enabled = false;
                txt_descripcion.Enabled = false;
                txt_editorial.Enabled = false;
                txt_idDoc.Enabled = false;
                txt_serie.Enabled = false;
                txt_Titulo.Enabled = false;
                txt_totalEjemplares.Enabled = false;
                txt_reservados.Enabled = false;
                txt_prestados.Enabled = false;
                chb_Virtual.Enabled = false;
                deshabilitarCamposTipoDoc();
            }
            else if (estado.EDITANDO())
            {
                txt_Autor.Enabled = true;
                cmb_tipodoc.Enabled = false;
                txt_clasificacion.Enabled = true;
                txt_descripcion.Enabled = true;
                txt_editorial.Enabled = true;
                txt_idDoc.Enabled = false;
                txt_serie.Enabled = true;
                txt_Titulo.Enabled = true;
                txt_totalEjemplares.Enabled = false;
                txt_reservados.Enabled = false;
                txt_prestados.Enabled = false;
                chb_Virtual.Enabled = false;
                habilitarCamposTipoDoc();
            }
        }

        private void habilitarCamposTipoDoc()
        {
            if (campos != null)
            {
                foreach (campoDocumento act in campos)
                {
                    act.campo().Enabled = true;
                }
            }
        }

        private void actualizarControles()
        {
            actualizarBotones();
            actualizarCampos();
        }

        private void limpiarCampos()
        {
            txt_Autor.Text = "";
            cmb_tipodoc.SelectedItem = null;
            txt_clasificacion.Text = "";
            txt_descripcion.Text = "";
            txt_editorial.Text = "";
            txt_idDoc.Text = "";
            txt_serie.Text = "";
            txt_Titulo.Text = "";
        }

        #endregion
        
        #region "acciones"

        private void aConsulta()
        {
            estado.consultar();
            limpiarCampos();
            actualizarControles();
        }

        private void aEditar()
        {
            if (estado.CONSULTANDO() && actual != null)
            {
                estado.editar();
                actualizarControles();
            }
        }

        private void aAgregar()
        {
            if (estado.CONSULTANDO())
            {
                estado.agregar();
                limpiarCampos();
                actualizarControles();
            }
        }

        private void agregarNuevo()
        {
            if (estado.AGREGANDO())
            {
                if (validaCamposAgregar())
                {
                    documento nuevo = getFromFields();
                    if (nuevo != null)
                    {
                        try
                        {
                            cp.ctrlDocumentos.agregarDocumento(nuevo);
                            mostrarInfo("Documento agregado");
                            aConsulta();
                        }
                        catch (Exception ex)
                        {
                            ventanaError(ex.Message);
                        }
                    }
                }
            }
        }

        private void editarActual()
        {
            if (estado.EDITANDO())
            {
                if (validarCamposEditar())
                {
                    documento nuevo = getFromFields();
                    if (nuevo != null)
                    {
                        try
                        {
                            cp.ctrlDocumentos.modificarDatos(actual.codDocumento, nuevo);
                            mostrarInfo("Los datos han sido actualizados");
                            aConsulta();
                        }
                        catch (Exception ex)
                        {
                            ventanaError(ex.Message);
                        }
                    }
                }
            }
        }

        private void eliminarActual()
        {
            if ((estado.EDITANDO()) || (estado.CONSULTANDO() && actual != null))
            {
                if (confirmarOperacion("Al eliminar el documento se eliminarán los ejemplares y los préstamos con este documento."))
                {
                    try
                    {
                        cp.ctrlDocumentos.eliminar(actual.codDocumento);
                        mostrarInfo("El documento y los datos relacionados han sido eliminados");
                    }
                    catch (Exception ex)
                    {
                        ventanaError(ex.Message);
                    }
                }
            }
        }

        #endregion
        
        #region "métodos botones"

        private void btn_cancelar_Click(object sender, EventArgs e)
        {
            aConsulta();
        }

        private void btn_Nuevo_Click(object sender, EventArgs e)
        {
            aAgregar();
        }

        private void btn_editar_Click(object sender, EventArgs e)
        {
            aEditar();
        }

        private void btn_eliminar_Click(object sender, EventArgs e)
        {
            eliminarActual();
        }

        private void btn_guardar_Click(object sender, EventArgs e)
        {
            if (estado.AGREGANDO())
            {
                agregarNuevo();
            }
            else if (estado.EDITANDO())
            {
                editarActual();
            }
        }

        #endregion

        #region "validacion"

        private bool validarCamposEditar()
        {
            bool valido = true;
            try
            {
                if (!cp.ctrlDocumentos.idValido(txt_idDoc.Text, true))
                {
                    erp_error.SetError(txt_idDoc, "Id del documento es inválido");
                    valido = false;
                }
                else
                {
                    erp_error.SetError(txt_idDoc, "");
                }

                if (!cp.ctrlDocumentos.tituloValido(txt_Titulo.Text))
                {
                    erp_error.SetError(txt_Titulo, "Titulo Inválido");
                    valido = false;
                }
                else
                {
                    erp_error.SetError(txt_Titulo, "");
                }
                if (!cp.ctrlDocumentos.descriptoresValidos(txt_descripcion.Text))
                {
                    erp_error.SetError(txt_descripcion, "Descriptores inválidos");
                    valido = false;
                }
                else
                {
                    erp_error.SetError(txt_descripcion, "");
                }
                if (!cp.ctrlDocumentos.clasificacionesValida(txt_clasificacion.Text))
                {
                    erp_error.SetError(txt_clasificacion, "Clasificación Inválida");
                    valido = false;
                }
                else
                {
                    erp_error.SetError(txt_clasificacion, "");
                }
                if (!cp.ctrlDocumentos.serieValida(txt_serie.Text))
                {
                    erp_error.SetError(txt_serie, "Serie Inválida");
                    valido = false;
                }
                else
                {
                    erp_error.SetError(txt_serie, "");
                }
                if (!cp.ctrlDocumentos.tipoDocumentoValoresValidos(tipoDocSelected(), valoresTipoDocumentos()))
                {
                    erp_error.SetError(pnl_atributos, "Algunos de los datos son incorrectos");
                    valido = false;
                }
                if (!cp.ctrlDocumentos.editorialValida(txt_editorial.Text))
                {
                    valido = false;
                    erp_error.SetError(txt_editorial, "Editorial Inválida");
                }
                else
                {
                    erp_error.SetError(txt_editorial, "");
                }
                if (!cp.ctrlDocumentos.editorialValida(txt_Autor.Text))
                {
                    valido = false;
                    erp_error.SetError(txt_Autor, "Autor Inválido");
                }
                else
                {
                    erp_error.SetError(txt_editorial, "");
                }
                return valido;
            }
            catch (Exception ex)
            {
                ventanaError(ex.Message);
                return false;
            }
        }

        private bool validaCamposAgregar()
        {
            return validarCamposEditar();
        }

        #endregion

        #region "atributos"

        #region "campos"

        LinkedList<campoDocumento> campos;
        int x = 12;
        int y = 10;
        int distY = 40;

        #endregion

        LinkedList<documento> datosActuales;
        LinkedList<tipoDocumento> tiposDocuemntos;
        documento actual;

        static int TODO = 1;
        static int XAUTOR = 2;
        static int XLIBRE = 3;
        static int XTITULO = 4;
        static int XCODIGO = 5;

        #endregion

        public int accion { get; set; }

        private void txb_busqueda_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Return)
            {
                btn_buscar_Click(null, null);
            }
        }

        private void btn_codBarras_Click(object sender, EventArgs e)
        {
            cp.abrirVentana(this, controlPrincipal.VENTANA_VISTA_PREVIA_CODIGOS, null);
        }
    }
}
